package com.yueqian.system.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yueqian.framework.entity.BaseEntity;
import com.yueqian.system.converter.MenuConvert;
import com.yueqian.system.entity.Menu;
import com.yueqian.system.mapper.MenuMapper;
import com.yueqian.system.service.MenuService;
import com.yueqian.system.vo.req.MenuReqVO;
import com.yueqian.system.vo.res.MenuResVO;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 菜单表 服务实现类.
 * </p>
 *
 * @author lxy
 * @since 2024-05-13
 */
@Service
@Slf4j
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Override
	public Long delete(Long id) {
        Menu entity = getById(id);
		this.removeById(id);
		return entity.getId();
    }

	@Override
	public List<MenuResVO> getMenus(MenuReqVO reqVO) {
		List<MenuResVO> menuResVOList = this.baseMapper.selectMenus();
		if (CollectionUtil.isNotEmpty(menuResVOList)) {
			menuResVOList.forEach(this::generateRoute);
		}
		return this.filterMenu(menuResVOList, reqVO);
	}


	/**
	 * 根据条件筛选菜单数据
	 *
	 * @param menus
	 * @param reqVO
	 */
	public List<MenuResVO> filterMenu(List<MenuResVO> menus, MenuReqVO reqVO) {
		if (CollectionUtil.isEmpty(menus)) {
			return new ArrayList<>();
		}
		if (ObjectUtil.isEmpty(reqVO.getName())) {
			return menus;
		}
		ArrayList<MenuResVO> menuResVOList = new ArrayList<>();
		for (MenuResVO menu : menus) {
			//只有一层节点
			if (StrUtil.contains(menu.getName(), reqVO.getName()) && CollectionUtil.isEmpty(menu.getChildren())) {
				menuResVOList.add(menu);
			}
			//包含子节点
			if (CollectionUtil.isNotEmpty(menu.getChildren()) && ObjectUtil.isNotEmpty(reqVO.getName())) {
				//父节点名称满足同时，又有子节点数据
				if (StrUtil.contains(menu.getName(), reqVO.getName())) {
					menuResVOList.add(menu);
					menu.setChildren(filterMenu(menu.getChildren(), reqVO));
				} else {
					//父节点不满足，子节点有数据
					List<MenuResVO> menuTreeResVOS1 = filterMenu(menu.getChildren(), reqVO);
					CollUtil.addAll(menuResVOList, menuTreeResVOS1);
				}
			}

		}
		return menuResVOList;
	}

	public MenuResVO generateRoute(MenuResVO menu) {
		//获取菜单和上级菜单拥有的角色
		List<String> roles = getMenuRoleByMenuId(menu.getId());
		menu.setRoles(roles);
		List<MenuResVO> menuList = getMenusByParentId(menu.getId());
		ArrayList<MenuResVO> menuResVOList = new ArrayList<>();
		for (MenuResVO menu1 : menuList) {
			MenuResVO menuTreeResVO = generateRoute(menu1);
			menuResVOList.add(menuTreeResVO);
			menu.setChildren(menuResVOList);
		}
		return menu;
	}

	//递归获取菜单父节点数据
	public void getParentMenuIds(Long parentId, List<Long> result) {
		List<Menu> menus = this.list(Wrappers.lambdaQuery(Menu.class).eq(ObjectUtil.isNotEmpty(parentId), Menu::getId, parentId));
		if (CollectionUtil.isNotEmpty(menus)) {
			List<Long> ids = menus.stream().map(BaseEntity::getId).collect(Collectors.toList());
			List<Long> parentIds = menus.stream().map(Menu::getParentId).collect(Collectors.toList());
			CollectionUtil.addAllIfNotContains(result, ids);
			for (Long id : parentIds) {
				this.getParentMenuIds(id, result);
			}
		}
	}


	@Transactional
	@Override
	public Long add(MenuReqVO reqVO) {
		Menu menu = MenuConvert.INSTANCE.toEntity(reqVO);
		this.saveOrUpdate(menu);
		return menu.getId();
	}

	@Override
	public MenuResVO getDetail(Long id) {
		MenuResVO menuResVO;
		List<MenuResVO> menuResVOList = this.getMenus(new MenuReqVO());
		Menu entity = baseMapper.selectById(id);
		//新增
		if (ObjectUtil.isEmpty(entity)) {
			Menu menu = new Menu();
			menuResVO = MenuConvert.INSTANCE.toRes(menu);
			menuResVO.setChildren(menuResVOList);
		} else { //编辑
			menuResVO = MenuConvert.INSTANCE.toRes(entity);
			menuResVO.setChildren(menuResVOList);
		}
		return menuResVO;
	}


	//通过父节点获取子节点
	public List<MenuResVO> getMenusByParentId(Long id) {
		return this.baseMapper.getMenusByParentId(id);
	}


	/**
	 * 获取菜单拥有那些权限
	 *
	 * @param id
	 */
	public List<String> getMenuRoleByMenuId(Long id) {
		return this.baseMapper.getMenuRoleByMenuId(id);
	}

}
